/*
@file: CodeTip.cpp
@author: ZZH
@date: 2022-11-04
@info: 代码提示框
*/
#include "CodeTip.h"
#include "symTable.h"

CodeTip::CodeTip(SignalEditor* bind, QWidget* parent): bindEditor(bind), QListWidget(parent)
{
    this->setBaseSize(30, 15);
    this->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
    this->setEditTriggers(EditTrigger::NoEditTriggers);
    this->hide();
    this->installEventFilter(this);

    connect(this, &CodeTip::clicked, this, [this]() {auto item = this->currentItem();if (nullptr != item) this->bindEditor->addSelectedItem(item);});
}

void CodeTip::requestCodeTip(const QPoint& pos, const QString& code)
{
    if (code.isEmpty())
        return;

    const QString& keyWord = code.section(QRegExp("[+-*/() ,\"]"), -1, -1);
    QRegExp rule(keyWord + ".*");

    for (auto it = FunSymTable.begin(); it != FunSymTable.end(); it++)
    {
        const auto& key = it.key();
        if (rule.exactMatch(key))
        {
            auto pItem = new QListWidgetItem(this);
            pItem->setText(key);
            pItem->setData(Qt::UserRole + 1, key.right(key.length() - keyWord.length()));
            pItem->setData(Qt::UserRole + 2, it.value().numOfArg);
            this->addItem(pItem);
        }
    }

    for (auto it = SigSymTable.begin(); it != SigSymTable.end(); it++)
    {
        const auto& key = it.key();
        if (rule.exactMatch(key))
        {
            auto pItem = new QListWidgetItem(this);
            pItem->setText(key);
            pItem->setData(Qt::UserRole + 1, key.right(key.length() - keyWord.length()));
            pItem->setData(Qt::UserRole + 2, -1);
            this->addItem(pItem);
        }
    }

    if (this->count() == 0)
        return;

    auto rect = this->geometry();
    rect.moveTopLeft(pos);
    this->setGeometry(rect);
    this->show();
    this->setFocus(Qt::FocusReason::PopupFocusReason);

    this->setCurrentRow(0);
}

void CodeTip::focusOutEvent(QFocusEvent* e)
{
    QListWidget::focusOutEvent(e);
    this->hide();
    this->clear();
    // this->releaseKeyboard();
    e->accept();
}

bool CodeTip::eventFilter(QObject* object, QEvent* event)
{
    if (object != this)
        return QListWidget::eventFilter(object, event);

    if (QEvent::KeyPress == event->type())
    {
        QKeyEvent* ke = static_cast<QKeyEvent*>(event);
        if (Qt::Key_Tab == ke->key())
        {
            this->keyPressEvent(ke);
            return true;
        }
    }

    return false;
}

void CodeTip::keyPressEvent(QKeyEvent* e)
{
    if (e->count() != 1)
        e->ignore();

    switch (e->key())
    {
        case Qt::Key_Tab://按下tab键
        // case Qt::Key_Space://按下空格键
        case Qt::Key_Enter://按下小键盘的enter键
        case Qt::Key_Return://按下字母键盘的enter
        {
            e->accept();
            auto curItem = this->currentItem();

            if (nullptr != curItem)
                this->bindEditor->addSelectedItem(curItem);
        }
        break;

        case Qt::Key_Up:
        {
            auto row = this->currentRow();
            this->setCurrentRow(row > 0 ? row - 1 : 0);
        }
        break;

        case Qt::Key_Down:
        {
            auto row = this->currentRow();
            this->setCurrentRow(row < this->count() ? row + 1 : row);
        }
        break;

        case Qt::Key_Escape:
        {
            e->accept();
            this->clearFocus();
        }
        break;

        default:
            this->bindEditor->keyPressEvent(e);
            break;
    }
}
